package com.dmw.service.Impl;

import com.dmw.Entity.DTO.UserLoginDTO;
import com.dmw.Entity.DTO.UserRegisterDTO;
import com.dmw.Entity.User;
import com.dmw.Entity.VO.UserLoginVO;
import com.dmw.ExceptionHandler.BusinessException;
import com.dmw.common.contant.JwtClaimsConstant;
import com.dmw.common.contant.MessageConstant;
import com.dmw.common.contant.StatusConstant;
import com.dmw.common.properties.JwtProperties;
import com.dmw.common.util.JwtUtil;
import com.dmw.mapper.UserMapper;
import com.dmw.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 用户登录
     *
     * @param userLoginDTO
     * @return
     */
    @Override
    public UserLoginVO login(UserLoginDTO userLoginDTO) {
        log.info("调用用户登录功能");
        String username = userLoginDTO.getUsername();
        String password = userLoginDTO.getPassword();
        //判断用户是否存在
        //mybatis方式
        User user = userMapper.getByUsername(username);
        if (user == null) {
            throw new BusinessException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        //验证密码是否正确
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new BusinessException(MessageConstant.PASSWORD_ERROR);
        }
        //验证账户状态
        if (user.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new BusinessException(MessageConstant.ACCOUNT_LOCKED);
        }

        //如果登录成功
        //生成JWT令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        claims.put(JwtClaimsConstant.USERNAME, user.getUsername());
        claims.put(JwtClaimsConstant.ROLE, user.getRole());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);
        //封装登录视图对象并返回
        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .role(user.getRole())
                .token(token)
                .build();
        //返回vo对象
        return userLoginVO;
    }

    /**
     * 用户注册
     * @param dto
     * @return
     */
    @Override
    public UserLoginVO register(UserRegisterDTO dto) {
        log.info("调用用户注册功能");
        // 1. 检查用户名是否存在
        if (userMapper.getByUsername(dto.getUsername()) != null) {
            throw new BusinessException(MessageConstant.ACCOUNT_ALREADY_EXIST);
        }

        // 2. 加密密码
        String encryptedPassword = new BCryptPasswordEncoder().encode(dto.getPassword());

        // 3. 构建用户
        User user = User.builder()
                .username(dto.getUsername())
                .password(encryptedPassword)
                .role("user")
                .status(StatusConstant.ENABLE)
                .createTime(LocalDateTime.now())

                .build();

        // 4. 保存用户
        userMapper.insert(user);

        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        claims.put(JwtClaimsConstant.USERNAME, user.getUsername());
        claims.put(JwtClaimsConstant.ROLE, user.getRole());
        // 5. 生成 JWT token
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        // 6. 构造 VO 返回
        return UserLoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .role(user.getRole())
                .token(token)
                .build();
    }
}
